home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / optimr.zip / OPTIMER.PAS < prev    next >
Pascal/Delphi Source File  |  1992-08-21  |  6KB  |  167 lines

  1. {$S-,R-,I-,V-,B-}
  2.  
  3. {*********************************************************}
  4. {*                   OPTIMER.PAS 1.0                     *}
  5. {*                by TurboPower Software                 *}
  6. {*********************************************************}
  7.  
  8. unit OpTimer;
  9.   {-Allows events to be timed with 1 microsecond resolution}
  10.  
  11. interface
  12.  
  13. uses
  14.   Dpmi;
  15.  
  16. procedure InitializeTimer;
  17.   {-Reprogram the timer chip to allow 1 microsecond resolution}
  18.  
  19. procedure RestoreTimer;
  20.   {-Restore the timer chip to its normal state}
  21.  
  22. function ReadTimer : LongInt;
  23.   {-Read the timer with 1 microsecond resolution}
  24.  
  25. function ElapsedTime(Start, Stop : LongInt) : Real;
  26.   {-Calculate time elapsed (in milliseconds) between Start and Stop}
  27.  
  28. function ElapsedTimeString(Start, Stop : LongInt) : string;
  29.   {-Return time elapsed (in milliseconds) between Start and Stop as a string}
  30.  
  31.   {==========================================================================}
  32.  
  33. implementation
  34.  
  35. const
  36.   TimerResolution = 1193181.667;
  37. var
  38.   SaveExitProc : Pointer;
  39.   Delta : LongInt;
  40.  
  41.   function Cardinal(L : LongInt) : Real;
  42.     {-Return the unsigned equivalent of L as a real}
  43.   begin                      {Cardinal}
  44.     if L < 0 then
  45.       Cardinal := 4294967296.0+L
  46.     else
  47.       Cardinal := L;
  48.   end;                       {Cardinal}
  49.  
  50.   function ElapsedTime(Start, Stop : LongInt) : Real;
  51.     {-Calculate time elapsed (in milliseconds) between Start and Stop}
  52.   begin                      {ElapsedTime}
  53.     ElapsedTime := 1000.0*Cardinal(Stop-(Start+Delta))/TimerResolution;
  54.   end;                       {ElapsedTime}
  55.  
  56.   function ElapsedTimeString(Start, Stop : LongInt) : string;
  57.     {-Return time elapsed (in milliseconds) between Start and Stop as a string}
  58.   var
  59.     R : Real;
  60.     S : string;
  61.   begin                      {ElapsedTimeString}
  62.     R := ElapsedTime(Start, Stop);
  63.     Str(R:0:3, S);
  64.     ElapsedTimeString := S;
  65.   end;                       {ElapsedTimeString}
  66.  
  67.   procedure InitializeTimer;
  68.     {-Reprogram the timer chip to allow 1 microsecond resolution}
  69.   begin                      {InitializeTimer}
  70.     {select timer mode 2, read/write channel 0}
  71.     Port[$43] := $34;        {00110100b}
  72.     inline($EB/$00);         {jmp short $+2 ;delay}
  73.     Port[$40] := $00;        {LSB = 0}
  74.     inline($EB/$00);         {jmp short $+2 ;delay}
  75.     Port[$40] := $00;        {MSB = 0}
  76.   end;                       {InitializeTimer}
  77.  
  78.   procedure RestoreTimer;
  79.     {-Restore the timer chip to its normal state}
  80.   begin                      {RestoreTimer}
  81.     {select timer mode 3, read/write channel 0}
  82.     Port[$43] := $36;        {00110110b}
  83.     inline($EB/$00);         {jmp short $+2 ;delay}
  84.     Port[$40] := $00;        {LSB = 0}
  85.     inline($EB/$00);         {jmp short $+2 ;delay}
  86.     Port[$40] := $00;        {MSB = 0}
  87.   end;                       {RestoreTimer}
  88.  
  89.   function ReadTimer : LongInt;
  90.     {-Read the timer with 1 microsecond resolution}
  91.   begin                      {ReadTimer}
  92.     inline(
  93.       $FA/                   {cli             ;Disable interrupts}
  94.       $BA/$20/$00/           {mov  dx,$20     ;Address PIC ocw3}
  95.       $B0/$0A/               {mov  al,$0A     ;Ask to read irr}
  96.       $EE/                   {out  dx,al}
  97.       $B0/$00/               {mov  al,$00     ;Latch timer 0}
  98.       $E6/$43/               {out  $43,al}
  99.       $EC/                   {in   al,dx      ;Read irr}
  100.       $89/$C7/               {mov  di,ax      ;Save it in DI}
  101.       $E4/$40/               {in   al,$40     ;Counter --> bx}
  102.       $88/$C3/               {mov  bl,al      ;LSB in BL}
  103.       $E4/$40/               {in   al,$40}
  104.       $88/$C7/               {mov  bh,al      ;MSB in BH}
  105.       $F7/$D3/               {not  bx         ;Need ascending counter}
  106.       $E4/$21/               {in   al,$21     ;Read PIC imr}
  107.       $89/$C6/               {mov  si,ax      ;Save it in SI}
  108.       $B0/$FF/               {mov  al,$0FF    ;Mask all interrupts}
  109.       $E6/$21/               {out  $21,al}
  110.      { $B8/$40/$00/}         {mov  ax,$40}                            {!!.20}
  111.       $A1/>BiosDataSele/     {mov  ax,$40     ;read low word of time}
  112.       $8E/$C0/               {mov  es,ax      ;from BIOS data area}
  113.       $26/$8B/$16/$6C/$00/   {mov  dx,es:[$6C]}
  114.       $89/$F0/               {mov  ax,si      ;Restore imr from SI}
  115.       $E6/$21/               {out  $21,al}
  116.       $FB/                   {sti             ;Enable interrupts}
  117.       $89/$F8/               {mov  ax,di      ;Retrieve old irr}
  118.       $A8/$01/               {test al,$01     ;Counter hit 0?}
  119.       $74/$07/               {jz   done       ;Jump if not}
  120.       $81/$FB/$FF/$00/       {cmp  bx,$FF     ;Counter > $FF?}
  121.       $77/$01/               {ja   done       ;Done if so}
  122.       $42/                   {inc  dx         ;Else count int req.}
  123.       {done:}
  124.       $89/$5E/$FC/           {mov [bp-4],bx   ;set function result}
  125.       $89/$56/$FE);          {mov [bp-2],dx}
  126.   end;                       {ReadTimer}
  127.  
  128.   procedure Calibrate;
  129.     {-Calibrate the timer}
  130.   const
  131.     Reps = 1000;
  132.   var
  133.     I : Word;
  134.     L1, L2, Diff : LongInt;
  135.   begin                      {Calibrate}
  136.     Delta := MaxInt;
  137.     for I := 1 to Reps do begin
  138.       L1 := ReadTimer;
  139.       L2 := ReadTimer;
  140.       {use the minimum difference}
  141.       Diff := L2-L1;
  142.       if Diff < Delta then
  143.         Delta := Diff;
  144.     end;
  145.   end;                       {Calibrate}
  146.  
  147.   {$F+}
  148.   procedure OurExitProc;
  149.     {-Restore timer chip to its original state}
  150.   begin                      {OurExitProc}
  151.     ExitProc := SaveExitProc;
  152.     RestoreTimer;
  153.   end;                       {OurExitProc}
  154.   {$F-}
  155.  
  156. begin
  157.   {set up our exit handler}
  158.   SaveExitProc := ExitProc;
  159.   ExitProc := @OurExitProc;
  160.  
  161.   {reprogram the timer chip}
  162.   InitializeTimer;
  163.  
  164.   {adjust for speed of machine}
  165.   Calibrate;
  166. end.
  167.